package com.boarsoft.config.core;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.common.util.FileUtil;

public class ConfigFileSyncImpl implements ConfigFileSync {
	private static final Logger log = LoggerFactory.getLogger(ConfigFileSyncImpl.class);

	/** 存放filecode对应的 listener */
	protected Map<String, ConfigListener> configListenerMap;

	/** 存放filecode对应的 文件路径 */
	protected Map<String, String> fileConfigMap = new ConcurrentHashMap<>();

	@Override
	public ReplyInfo<Object> remove(String code, String frp) {
		log.info("Remove config file {} = {}", code, frp);
		if (configListenerMap == null) {
			log.info("No config listeners here");
			return new ReplyInfo<Object>("no listener");
		}
		ConfigListener cl = this.getConfigListener(code);
		if (cl == null) {
			log.info("No config listener for {} = {}", code, frp);
			// 找不到合适的适配器表示不做处理，仍然返回true
			return new ReplyInfo<Object>(true, "No such config listener");
		}
		String ap = null;
		try {
			ap = cl.getAbosultePath(frp);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		if (FileUtil.deleteFile(ap)) {
			if (cl.onRemove(frp)) {
				return ReplyInfo.SUCCESS;
			}
		}
		log.error("Remove config file failed, {} = {}", code, frp);
		return new ReplyInfo<Object>("Remove config file failed");
	}

	@Override
	public ReplyInfo<Object> syncOne(byte[] bytes, String code, String frp) {
		return this.sync(bytes, code, frp);
	}

	protected ReplyInfo<Object> sync(byte[] bytes, String code, String frp) {
		log.info("Recevied new config file {} = {}", code, frp);
		if (configListenerMap == null) {
			log.info("No config listeners here");
			return new ReplyInfo<>("No config listeners here");
		}
		ConfigListener cl = this.getConfigListener(code);
		if (cl == null) {
			log.info("No config listener for {} = {}", code, frp);
			// 找不到合适的适配器表示不做处理，仍然返回true
			return new ReplyInfo<>(true, "No such config listener");
		}
		String ap = null;
		try {
			ap = cl.getAbosultePath(frp);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
		if (this.save(ap, bytes)) {
			if (cl.onReady(frp)) {
				return ReplyInfo.SUCCESS;
			}
		}
		log.error("Write config file failed, {} = {}", code, frp);
		return new ReplyInfo<Object>("Write config file failed");
	}

	public boolean save(String fp, byte[] bytes) {
		log.warn("Save config file to {}", fp);
		try {
			File f = new File(fp);
			FileUtil.makePath(f.getParent());
			FileUtil.writeBytes(f, bytes);
			return true;
		} catch (Exception e) {
			log.error("Error on write config file {}", fp, e);
			return false;
		}
	}

	public ConfigListener getConfigListener(String code) {
		if (configListenerMap.containsKey(code)) {
			return configListenerMap.get(code);
		}
		return configListenerMap.get("default");
	}

	public Map<String, ConfigListener> getConfigListenerMap() {
		return configListenerMap;
	}

	public void setConfigListenerMap(Map<String, ConfigListener> configListenerMap) {
		this.configListenerMap = configListenerMap;
	}

	public Map<String, String> getFileConfigMap() {
		return fileConfigMap;
	}

	public void setFileConfigMap(Map<String, String> fileConfigMap) {
		this.fileConfigMap = fileConfigMap;
	}
}